# Расширение сущности "Component" для генерации символов представления компонентов
entities:
  components:
    api:

    # Представления контекстов в PlantUML
    presentations:
      symbol:
        title: Символ компонента
        params:
          title: Требуемые параметры для презентации
          type: object
          properties:
            "dh-context-id":
              title: Идентификатор контекста
              type: string
              pattern: ^[a-zA-Z][a-zA-Z0-9_-]*(\.[a-zA-Z][a-zA-Z0-9_-]*)*$
          required:
            - dh-context-id
        type: symbol      # Указываем специальный тип презентации - "Символ"
        $constructor: >   # Переносим необходимую информацию из контекста в презентацию 
          (
            $id := $params."dh-context-id";
            $context := $lookup(contexts, $id);
            $prototype := entities.contexts.presentations.plantuml;
          
            /* Преобразует относительные пути к файлам в прямые*/
            $toDirectRes := function($value) {
                $substring($value, 0, 4) = "res:" ? $value : "res://contexts/" & $id & "#" & $value
            };

            /* Если явно указан puml файл, просто рендерим его */
            $substring($context.uml, -5) = ".puml" ? (
                {
                  "type": "plantuml",
                  "source": $toDirectRes($context.uml)
                }
            ) : (
                $result := $context.source ? ($merge([$prototype, {
                    "origin": { "_source": $context.source, "_origin": "($)" }
                }])) : $prototype;

                /* Если в контексте переопределен шаблон, используем его по прямой ссылке */
                $result := $context.template 
                    ? $merge([$result, { "template":  $toDirectRes($context.template) }])
                    : $result;
            )
          )
        template: templates/template.puml
        source: >
          (
            $id := $params."dh-context-id";
            /* Получаем доступ к оригинальным данным */
            $manifest := _origin ? _origin : $;
            /* Получаем контекст */
            $context := $lookup($manifest.contexts, $id);
            /* Если в контексте задан источник, берем его за основу */
            $manifest := _source ? _source : $;
          
            $isExtraLinks := $not($string($context."extra-links") = "false");
          
            /* Получаем коллекцию дефолтных вспомогательных функций */
            $defFunctions := $manifest.entities.contexts.api;
          
            /* Получаем коллекцию дефолтных параметров */
            $defConfig := $manifest.entities.contexts.config; 
          
            /* Определяем движок рендеринга */
            $renderCore := $lookup({
              "elk": "!pragma layout elk",
              "smetana": "!pragma layout smetana"
            }, $defConfig.renderCore);

            /* Формируем заголовок */
            $header := "$Header(\"" & ($context.title ? $context.title : $id ) & "\", , , )\n";

            /* Получаем все компоненты входящие в контекст */
            $components := $eval($defFunctions.fetchComponents, {
              "manifest": $manifest,
              "contextId": $id,
              "extra-links": $isExtraLinks,
              "componentId": $params.componentId
            });

            /* Генерируем области */
            $areas := $eval($defFunctions.fetchAreas, {
              "components": $components
            });
          
            /* Генерируем PlantUML диаграмму компонентов */
            $elements := $eval($defFunctions.makePumlComponentDiagram, {
              "manifest": $manifest,
              "areas": $areas,
              "components": $components
            });

            /* Получаем список связей */
            $links := $eval($defFunctions.fetchLinks, {
              "components": $components
            });
          
            /* Генерируем код связей */
            $linksCode := $eval($defFunctions.makePumlComponentsLinks, {
              "links": $links
            });
          
            /* Готовим данные для передачи в шаблон */
            {
              "renderCore": $renderCore,
              "presentation": $defConfig.defaultPresentation,
              "code": $header & $elements & $linksCode
            }
          )
